iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 23
0
自我挑戰組

30 Days 如何把 C 語言偽裝成高階語言 OWO /系列 第 24

Day 23: goto、標記、爭議及反面例子

  • 分享至 

  • xImage
  •  

▌第一次閱讀本系列的,可以先看:

本系列的大綱 傳送門


goto、標記:

goto 格式: goto [標記];
標記 格式: [標記]:

用於無條件跳躍到標記語句,基礎用法:

printf("Hello");
goto label;
printf(" World!!!");
label:

輸出: Hello
跳過了 printf(" World!!!"); 語句。


  • goto 陳述式 不能夠在函數間跳躍
    跳躍範圍局限於同一個函數內。

  • [標記] 這個識別項擁有自己的命名空間
    故此不會與一般變數名稱衝突,但依然不能設定為關鍵字/保留字。
    .
    正因為擁有自己的命名空間
    所以不能夠用變數作為 [標記] 或者 goto 目標。

  • [標記] 的視野範圍(scope)不會受 for, while 等區域局限,
    直接擁有整個函數內的視野範圍

  • goto 可以多個,
    但是 [標記] 是唯一的。

▌爭議:

goto 一直以來充滿爭議,被不建議使用,
一些程式風格禁止使用 goto 陳述式。

根據 goto - 維基百科,自由的百科全書

主要原因是 goto 陳述式 容易大幅降低可讀性
甚至成為不可維護的「麵條程式碼」,
使程式事情的難以追蹤和理解,以及修改

有一些為 goto 陳述式辯護的人認為,
加以限制地使用GOTO陳述式不會導致低質素的程式碼,
並且聲稱一些任務如果不使用一條或多條GOTO陳述式是無法被直接實現的。
如有限狀態自動機的實現、跳出巢狀迴圈以及例外處理。


▌限制不使用 goto 的實現方式:

先嘗試一個用 goto + 標記 做例外處理的例子:

/*陳述式*/
if(/*錯誤檢測*/){
    goto ex_catch;
}
back_to_call:
/*陳述式*/

ex_catch:
/*錯誤處理*/
goto back_to_call;

可讀性已經很差,不過下面那個更加離譜......。

當錯誤檢測成立跳轉到錯誤處理,
最後返回錯誤檢測的位置。

上式與 try-catch(例外處理) 的跳轉類似,
返回發生錯誤的位置。


若果強制限制不使用 goto 的實現方式,

實現方式會變成如何?

int error_is_not_happened = 1;
do{
    do{
        if(error_is_not_happened){
            /*陳述式*/
            if(/*錯誤檢測*/){
                error_is_not_happened = 0
                break;
            }
        }
        error_is_not_happened = 1
        /*陳述式*/
    while(0);
/*錯誤處理*/
while(!error_is_not_happened);

可能有更簡單的實現方法,不過我隨便/暫時想到的是這樣。

宣告了變數標記 error_is_not_happened非零為真

利用 do{}while(0) 加上錯誤檢測成立後的 break;
快速跳離整個陳述式,到達函式的最底部分,進行錯誤處理

再利用 while(!error_is_not_happened) 判斷,
判斷到達這裏(最底部分)的原因是否因為發生了錯誤
,返回最頂部分
,即是以正常運行步驟到達最底部分,允許離開

返回最頂部分後,利用 if(error_is_not_happened){}
快速返回錯誤檢測後的位置,
再把 error_is_not_happened 標記賦值為一(true),允許從最底部分離開。

【其實我是覺得上面這一大堆文字已經沒有什麼人想讀了。】


所以:

這樣的可讀性絕對不高吧......這還是只有一個例外處理的情況。
更多例外處理需要使用 更多的 變數標記,
更多的 do{}while(), break ,以及更多的標記判斷。

所以在某些情況下使用 goto 的確會比較方便,
甚至比較可讀。


▌參考資料:

goto - 維基百科,自由的百科全書
https://zh.wikipedia.org/zh-hk/Goto#%E5%AF%B9%E4%BA%8Egoto%E4%BD%BF%E7%94%A8%E7%9A%84%E6%89%B9%E8%AF%84
麵條式程式碼 - 維基百科,自由的百科全書
https://zh.wikipedia.org/wiki/%E9%9D%A2%E6%9D%A1%E5%BC%8F%E4%BB%A3%E7%A0%81


上一篇
Day 22:重溫 可變參數函數、可變參數宏 __VA_ARGS__
下一篇
Day 24: 例外處理系列:極粗略實現、使用例子
系列文
30 Days 如何把 C 語言偽裝成高階語言 OWO /31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言